home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Text Editor / Source / TextEditorLayout.cpp < prev    next >
Encoding:
Text File  |  1995-12-13  |  48.6 KB  |  1,606 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  
  3.     File:            TextEditorLayout.cpp
  4.     
  5.     Description:    TextEditor's layout protocol methods.
  6.         
  7.     Written by:        Steve Smith
  8.     
  9.     Copyright:        © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  10.     
  11. ------------------------------------------------------------------------------*/
  12.  
  13. // Notification that this is a SOM source file
  14. #define SampleCode_TextEditor_Class_Prototypes
  15. // define underscore (_) field names
  16. #define VARIABLE_MACROS
  17.  
  18. #ifndef _COMPILERDEFS_
  19. #include "CompDefs.h"
  20. #endif
  21.  
  22. // -- OpenDoc Utilities --
  23.  
  24. #ifndef _EXCEPT_
  25. // Exceptions define several important macros (e.g. CHECKENV)
  26. // which are used in the SOM method dispatch glue. If Except.h
  27. // is not included early enough, exceptions may not be thrown
  28. // correctly when returning from a SOM method with "ev" parameter set.
  29. #include <Except.h>
  30. #endif
  31.  
  32. // -- TextEditor Includes
  33.  
  34. #ifndef SOM_SampleCode_TextEditor_xih
  35. #include "TextEditor.xih"
  36. #endif
  37.  
  38. #ifndef _TEXTEDITORDEF_
  39. #include "TextEditorDef.h"
  40. #endif
  41.  
  42. #ifndef _TEXTEDITORUTILS_
  43. #include "TextEditorUtils.h"
  44. #endif
  45.  
  46. #ifndef _TEXTEDITORGLOBALS_
  47. #include "TextEditorGlobals.h"
  48. #endif
  49.  
  50. // -- OpenDoc Includes --
  51.  
  52. #ifndef _ODTYPES_
  53. #include <ODTypes.h>
  54. #endif
  55.  
  56. #ifndef SOM_ODArbitrator_xh
  57. #include <Arbitrat.xh>
  58. #endif
  59.  
  60. #ifndef SOM_ODCanvas_xh
  61. #include <Canvas.xh>
  62. #endif
  63.  
  64. #ifndef SOM_ODDispatcher_xh
  65. #include <Disptch.xh>
  66. #endif
  67.  
  68. #ifndef SOM_ODFrame_xh
  69. #include <Frame.xh>
  70. #endif
  71.  
  72. #ifndef SOM_ODFrameFacetIterator_xh
  73. #include <FrFaItr.xh>
  74. #endif
  75.  
  76. #ifndef SOM_ODNameSpaceManager_xh
  77. #include <NmSpcMg.xh>
  78. #endif
  79.  
  80. #ifndef SOM_ODObjectNameSpace_xh
  81. #include <ObjectNS.xh>
  82. #endif
  83.  
  84. #ifndef SOM_ODSession_xh
  85. #include <ODSessn.xh>
  86. #endif
  87.  
  88. #ifndef SOM_ODPart_xh
  89. #include <Part.xh>
  90. #endif
  91.  
  92. #ifndef SOM_ODShape_xh
  93. #include <Shape.xh>
  94. #endif
  95.  
  96. #ifndef SOM_ODStorageUnit_xh
  97. #include <StorageU.xh>
  98. #endif
  99.  
  100. #ifndef SOM_ODTransform_xh
  101. #include <Trnsform.xh>
  102. #endif
  103.  
  104. #ifndef SOM_ODWindow_xh
  105. #include <Window.xh>
  106. #endif
  107.  
  108. #ifndef SOM_ODWindowState_xh
  109. #include <WinStat.xh>
  110. #endif
  111.  
  112. // -- OpenDoc Utilities --
  113.  
  114. #ifndef _BNDNSUTL_
  115. #include <BndNSUtl.h>
  116. #endif
  117.  
  118. #ifndef _ISOSTR_
  119. #include <ISOStr.h>
  120. #endif
  121.  
  122. #ifndef _ITEXT_
  123. #include <IText.h>
  124. #endif
  125.  
  126. #ifndef _ODMEMORY_
  127. #include <ODMemory.h>
  128. #endif
  129.  
  130. #ifndef _ODUTILS_
  131. #include <ODUtils.h>
  132. #endif
  133.  
  134. #ifndef _TEMPITER_
  135. #include <TempIter.h>
  136. #endif
  137.  
  138. #ifndef _TEMPOBJ_
  139. #include <TempObj.h>
  140. #endif
  141.  
  142. #ifndef _USERSRCM_
  143. #include <UseRsrcM.h>
  144. #endif
  145.  
  146. // -- Macintosh Includes --
  147.  
  148. #ifndef __ICONS__
  149. #include <Icons.h>
  150. #endif
  151.  
  152. #ifndef __QUICKDRAW__
  153. #include <Quickdraw.h>
  154. #endif
  155.  
  156. // -- Textension Includes --
  157.  
  158. #ifndef _Textension_
  159. #include "Textension.h"
  160. #endif
  161.  
  162. #ifndef _TSMTextension_
  163. #include "TSMTextension.h"
  164. #endif
  165.  
  166.  
  167. //------------------------------------------------------------------------------
  168. // Method:        DisplayFrameAdded
  169. // Origin:        ODPart
  170. //
  171. // Description:    This method is called in response to a frame being created for
  172. //                the part.
  173. //
  174. //                The part records the existence of a new display frame in its
  175. //                internal display frame list, as well as, verify that the frame
  176. //                is "set up" correctly (i.e., valid viewType). The part also
  177. //                creates and stores its "frame info" class in the new frame. 
  178. //------------------------------------------------------------------------------
  179. #pragma segment TextEditorLayout
  180.  
  181. SOM_Scope    void
  182. SOMLINK        TextEditor__DisplayFrameAdded
  183.             (
  184.                 SampleCode_TextEditor*        somSelf,
  185.                 Environment*                ev,
  186.                 ODFrame*                    frame
  187.             )
  188. {
  189.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  190.     SOMMethodDebug("TextEditor","DisplayFrameAdded");
  191.  
  192.     SOM_TRY
  193.         
  194.         // If we are being embedded in another part, the presentation field
  195.         // will (most likely) be unset; we need to set it something meaningful.
  196.         // The view field may also be unset, if so, we prefer to be displayed
  197.         // in a frame view.
  198.     
  199.         if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation
  200.           && frame->GetPresentation(ev) != gGlobals->fRulerPresentation)
  201.             frame->SetPresentation(ev, gGlobals->fMainPresentation);
  202.         
  203.         if ( frame->GetViewType(ev) == kODNullTypeToken )
  204.             frame->SetViewType(ev, gGlobals->fFrameView);
  205.         
  206.         if ( frame->GetPresentation(ev) == gGlobals->fMainPresentation )
  207.         {
  208.             // Tell OpenDoc the frame can accept dragged content.
  209.             frame->SetDroppable(ev, kODTrue);
  210.             
  211.             // Hang our "state" info off of the new display frame. We use
  212.             // the CFrameInfo object for activation, updating, and window
  213.             // maintenance.
  214.             CFrameInfo* frameInfo = new CFrameInfo(ODGetSession(ev, somSelf));
  215.             frame->SetPartInfo(ev, (ODInfoType)frameInfo);
  216.                 
  217.             // If the frame being added is a root frame, we know that a window
  218.             // is associated with this frame. Notify ourselves that we need to 
  219.             // clean it up when the frame goes away.
  220.             if ( frame->IsRoot(ev) )
  221.                 frameInfo->SetShouldDisposeWindow(kODTrue);
  222.     
  223.             // The proxy class will refcount the frame passed to it, so we
  224.             // don't need to worry about refcounting the display frame.
  225.             CFrameProxy* proxy = new CFrameProxy;
  226.             proxy->InitFrameProxy(ev,frame);
  227.         
  228.             // Add the proxy to the display frame collection.
  229.             _fDisplayFrames->Add(proxy);
  230.             
  231.             // Since we maintain a persistent list of weak references to our
  232.             // display frames, having one added to the part dirties it.
  233.             somSelf->SetDirty(ev);
  234.  
  235.             // Embedded frames are sequenced.
  236.             if ( !frame->IsRoot(ev) )
  237.             {
  238.                 long seqNumber = 1;    // $$$$$$
  239.                 
  240.                 frame->ChangeSequenceNumber(ev, seqNumber);
  241.                 
  242.                 _fPageMargins.top = _fPageMargins.left = _fPageMargins.bottom =
  243.                     _fPageMargins.right = kDefaultEmbeddedMargin;  /* pixels */
  244.                     // Set default margins
  245.             }
  246.         }
  247.     
  248.     SOM_CATCH_ALL
  249.     SOM_ENDTRY
  250. }
  251.  
  252. //------------------------------------------------------------------------------
  253. // Method:        DisplayFrameConnected
  254. // Origin:        ODPart
  255. //
  256. // Description:    This method is called when one of our display frames, previously
  257. //                written out, is internalized. This method is called instead of
  258. //                DisplayFrameAdded because a "new" frame is not being created;
  259. //                an existing one is being reconstituted.
  260. //
  261. //                The part has nothing special to do, so we just add it to the
  262. //                part's internal display frame list.
  263. //------------------------------------------------------------------------------
  264. #pragma segment TextEditorLayout
  265.  
  266. SOM_Scope    void
  267. SOMLINK        TextEditor__DisplayFrameConnected
  268.             (
  269.                 SampleCode_TextEditor*        somSelf,
  270.                 Environment*                ev,
  271.                 ODFrame*                    frame
  272.             )
  273. {
  274.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  275.     SOMMethodDebug("TextEditor","DisplayFrameConnected");
  276.  
  277.     SOM_TRY
  278.     
  279.         // Iterate over our display collection to match the frame with
  280.         // an existing proxy with the correct frame ID. If we find it,
  281.         // replace the ID with the actual frame. If we don't find it,
  282.         // treat it as a newly "added" frame.
  283.         ODBoolean found = kODFalse;
  284.         CListIterator fiter(_fDisplayFrames);
  285.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  286.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  287.         {
  288.             if ( proxy->GetID() == frame->GetID(ev) )
  289.             {
  290.                 // The proxy class will refcount the frame passed to it, so we
  291.                 // don't need to worry about refcounting the display frame.
  292.                 proxy->SetFrame(ev,frame);
  293.                 found = kODTrue;
  294.             }
  295.         }
  296.  
  297.         // Parts typically operate under the assumption that they have previous
  298.         // knowledge of a frame before it is connected to it. This knowledge
  299.         // should come from having read in the frame reference when the part
  300.         // was internalized. If the frame is an "unknown", the part was probably
  301.         // bound to another editors storage unit because the editor is missing or
  302.         // the user changed the editor in the Info dialog. 
  303.         if ( found )
  304.         {
  305.             // If a display frame is connected to us with an unrecognizable
  306.             // presentation, we need to set it to something meaningful.
  307.             if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation
  308.               && frame->GetPresentation(ev) != gGlobals->fRulerPresentation)
  309.                 frame->SetPresentation(ev, gGlobals->fMainPresentation);
  310.             
  311.             // Handle the main presentation.
  312.             if ( frame->GetPresentation(ev)    == gGlobals->fMainPresentation )
  313.             {
  314.                 // If the frame being added is a root frame, we know that a window
  315.                 // is associated with this frame. Notify ourselves that we need to 
  316.                 // clean it up when the frame goes away.
  317.                 if ( frame->IsRoot(ev) )
  318.                 {
  319.                     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  320.                     frameInfo->SetShouldDisposeWindow(kODTrue);
  321.             
  322.                     // In addition, we need to verify that the frame is in "frame" view.
  323.                     // If the user dragged an icon from a document to Finder and then
  324.                     // opens the resultant document, the view would be "icon". However
  325.                     // displaying a icon is useless, so we need to change the view to
  326.                     // frame.
  327.                     if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  328.                         frame->SetViewType(ev, gGlobals->fFrameView);    
  329.                 }
  330.                 
  331.                 // Tell OpenDoc the frame can accept dragged content.
  332.                 frame->SetDroppable(ev, kODTrue);
  333.             }
  334.         }
  335.         else
  336.         {
  337.             // If an unrecognizable frame is connected to us, treat it like a "new"
  338.             // frame and call our method to add it.
  339.             somSelf->DisplayFrameAdded(ev, frame);
  340.         }
  341.         
  342.     SOM_CATCH_ALL
  343.     SOM_ENDTRY
  344. }
  345.  
  346. //------------------------------------------------------------------------------
  347. // Method:        DisplayFrameRemoved
  348. // Origin:        ODPart
  349. //
  350. // Description:    This method is called in response to a frame being removed from
  351. //                the part.
  352. //
  353. //                The part removes the frame from its internal display frame list
  354. //                and reliquishes any foci that it still owned. Lastly, if the
  355. //                frame has a source frame (it was the root frame of a part
  356. //                window), we will record the part window bounds so that any
  357. //                subsequent part windows opened on the source frame will appear
  358. //                in the same location.
  359. //------------------------------------------------------------------------------
  360. #pragma segment TextEditorLayout
  361.  
  362. SOM_Scope    void
  363. SOMLINK        TextEditor__DisplayFrameRemoved
  364.             (
  365.                 SampleCode_TextEditor*        somSelf,
  366.                 Environment*                ev,
  367.                 ODFrame*                    frame
  368.             )
  369. {
  370.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  371.     SOMMethodDebug("TextEditor","DisplayFrameRemoved");
  372.  
  373.     if ( frame->GetPresentation(ev)    == gGlobals->fRulerPresentation )
  374.         return;
  375.     
  376.     SOM_TRY
  377.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  378.  
  379.         // Make sure the frame going away doesn't own any foci. Forgetting
  380.         // to do this, will cause a "refcounting" error when the frame
  381.         // is deleted by the draft.
  382.         somSelf->RelinquishAllFoci(ev, frame);
  383.  
  384.         // Clean up the display frame.
  385.         somSelf->CleanupDisplayFrame(ev, frame, kFrameRemoved);
  386.         
  387.         // Clean up any associated window.
  388.         somSelf->CleanupWindow(ev, frame);
  389.                 
  390.         // Dispose of the frame's runtime state info.
  391.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  392.         ODDeleteObject(frameInfo);
  393.         
  394.         // Remove the display frame from our collection.
  395.         CListIterator fiter(_fDisplayFrames);
  396.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  397.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  398.         {
  399.             if ( ODObjectsAreEqual(ev, proxy->GetFrame(ev), frame) )
  400.             {
  401.                 // Delete the proxy object and its contents. The frame's
  402.                 // refcount will be decremented in the proxy destructor.
  403.                 fiter.RemoveCurrent();
  404.                 delete proxy;
  405.             }
  406.         }
  407.  
  408.         // Since we maintain a persistent list of weak references to our
  409.         // display frames, having one removed from the part dirties it.
  410.         somSelf->SetDirty(ev);
  411.         
  412.     SOM_CATCH_ALL
  413.         // Alert the user of the problem.
  414.         somSelf->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  415.         // Change the exception value, so the DocShell doesn't display an
  416.         // error dialog.
  417.         SetErrorCode(kODErrAlreadyNotified);
  418.     SOM_ENDTRY
  419. }
  420.  
  421. //------------------------------------------------------------------------------
  422. // Method:        DisplayFrameClosed
  423. // Origin:        ODPart
  424. //
  425. // Description:    This method is called in response to a frame being closed as a
  426. //                result of the document having been closed by the user.
  427. //
  428. //                The part behaves much the same way that it would if a frame were
  429. //                removed (see above), except that we don't need to cache runtime
  430. //                information. 
  431. //------------------------------------------------------------------------------
  432. #pragma segment TextEditorLayout
  433.  
  434. SOM_Scope    void
  435. SOMLINK        TextEditor__DisplayFrameClosed
  436.             (
  437.                 SampleCode_TextEditor*        somSelf,
  438.                 Environment*                ev,
  439.                 ODFrame*                    frame
  440.             )
  441. {
  442.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  443.     SOMMethodDebug("TextEditor","DisplayFrameClosed");
  444.  
  445.     if ( frame->GetPresentation(ev)    == gGlobals->fRulerPresentation )
  446.         return;
  447.     
  448.     SOM_TRY
  449.     
  450.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  451.  
  452.         // Make sure the frame going away doesn't own any foci. Forgetting
  453.         // to do this, will cause a "refcounting" error when the frame
  454.         // is deleted by the draft.
  455.         somSelf->RelinquishAllFoci(ev, frame);
  456.  
  457.         // Clean up the display frame.
  458.         somSelf->CleanupDisplayFrame(ev, frame, kFrameClosed);
  459.         
  460.         // Clean up any associated window.
  461.         somSelf->CleanupWindow(ev, frame);
  462.  
  463.         // Dispose of the frame's runtime state info.
  464.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  465.         ODDeleteObject(frameInfo);
  466.         
  467.         // Remove the display frame from our collection.
  468.         CListIterator fiter(_fDisplayFrames);
  469.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  470.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  471.         {
  472.             if ( proxy->GetID() == frame->GetID(ev) )
  473.             {
  474.                 // Release the frame reference, but don't get rid of the
  475.                 // proxy object because "closed" frames may be reconnected
  476.                 // before the document is closed.
  477.                 proxy->Purge(ev);
  478.             }
  479.         }
  480.         
  481.     SOM_CATCH_ALL
  482.         // Alert the user of the problem.
  483.         somSelf->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  484.         // Change the exception value, so the DocShell doesn't display an
  485.         // error dialog.
  486.         SetErrorCode(kODErrAlreadyNotified);
  487.     SOM_ENDTRY
  488. }
  489.  
  490. //------------------------------------------------------------------------------
  491. // Method:        CleanupDisplayFrame
  492. // Origin:        TextEditor
  493. //
  494. // Description:    This method is called when a frame has been closed or removed.
  495. //                The method cleans up the references and state information stored
  496. //                in the CFrameInfo class.
  497. //------------------------------------------------------------------------------
  498. #pragma segment TextEditorLayout
  499.  
  500. SOM_Scope    void
  501. SOMLINK        TextEditor__CleanupDisplayFrame
  502.             (
  503.                 SampleCode_TextEditor*        somSelf,
  504.                 Environment*                ev,
  505.                 ODFrame*                    frame,
  506.                 ODBoolean                    frameRemoved
  507.             )
  508. {
  509.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  510.     SOMMethodDebug("TextEditor","CleanupDisplayFrame");
  511.  
  512.     if ( frame->GetPresentation(ev)    == gGlobals->fRulerPresentation )
  513.         return;
  514.     
  515.     SOM_TRY
  516.     
  517.         ODError        error = noErr;
  518.         CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  519.     
  520.         TRY
  521.             // If we are the root of a child window, we need to notify
  522.             // our source frame that we are going away.
  523.             if ( frameInfo->HasSourceFrame() )
  524.             {
  525.                 ODFrame* sourceFrame = frameInfo->GetSourceFrame(ev);
  526.                 CFrameInfo* sourceFrameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
  527.     
  528.                 if ( frameRemoved )
  529.                 {
  530.                     // Invalidate the source frame. We do this because the
  531.                     // source frame may have a unique display when it has
  532.                     // been opened into a part window. This forces the
  533.                     // frame to redraw "not opened".
  534.                     sourceFrame->Invalidate(ev, kODNULL, kODNULL);
  535.                 }
  536.                 
  537.                 // Tell the source frame that its dependent is going away.
  538.                 sourceFrameInfo->ReleaseDependentFrame(ev);            
  539.     
  540.                 // Release our reference to the source frame.
  541.                 frameInfo->ReleaseSourceFrame(ev);
  542.     
  543.                 // If the frame is the root, it is a part window going away
  544.                 // and we need to notify our source frame that it no longer
  545.                 // has a part window.
  546.                 if ( frame->IsRoot(ev) )
  547.                     sourceFrameInfo->SetPartWindow(ev, kODNULL);
  548.             }
  549.         CATCH_ALL
  550.             error = ErrorCode();
  551.         ENDTRY
  552.         
  553.         TRY
  554.             // If the frame was removed from the document, we need to remove
  555.             // any child window displaying that frame.
  556.             if ( frameRemoved )
  557.             {
  558.                 // If we have a child window, we need to close it.
  559.                 ODWindow* window = frameInfo->AcquirePartWindow(ev);
  560.  
  561.                 if ( window )
  562.                 {
  563.                     frameInfo->SetPartWindow(ev, kODNULL);
  564.                     window->CloseAndRemove(ev);
  565.                 }
  566.             }
  567.         CATCH_ALL
  568.             error = ErrorCode();
  569.         ENDTRY
  570.     
  571.         TRY
  572.             // If we have dependent frames, we need to notify them that we
  573.             // are going away.
  574.         
  575.             if ( frameInfo->HasDependentFrame() )
  576.             {
  577.                 // Get the frame that is dependent on this one. We can safely
  578.                 // do this because we only reference our own display frames.
  579.                 ODFrame* dependentFrame = frameInfo->GetDependentFrame(ev);
  580.                 CFrameInfo* dependentFrameInfo = (CFrameInfo*) dependentFrame->GetPartInfo(ev);
  581.     
  582.                 // Tell the dependent frame that its source is going away.
  583.                 dependentFrameInfo->ReleaseSourceFrame(ev);
  584.                 
  585.                 // Release our reference to the dependent frame.
  586.                 frameInfo->ReleaseDependentFrame(ev);
  587.             }
  588.         CATCH_ALL
  589.             error = ErrorCode();
  590.         ENDTRY
  591.         
  592.         // If anything went wrong, signal an error.
  593.         THROW_IF_ERROR(error);
  594.     
  595.     SOM_CATCH_ALL
  596.     SOM_ENDTRY
  597. }
  598.  
  599. //------------------------------------------------------------------------------
  600. // Method:        AttachSourceFrame
  601. // Origin:        ODPart
  602. //
  603. // Description:    If the part which we are contained in is opened into a part
  604. //                window, it is required to iterate over its embedded frames and
  605. //                add new display frames in the part window. After each new
  606. //                embedded frame is created, this method will be called.
  607. //
  608. //                Given all that, and given our lack of interesting
  609. //                content, we just validate the frame and attach it to its source.
  610. //------------------------------------------------------------------------------
  611. #pragma segment TextEditorLayout
  612.  
  613. SOM_Scope    void
  614. SOMLINK        TextEditor__AttachSourceFrame
  615.             (
  616.                 SampleCode_TextEditor*        somSelf,
  617.                 Environment*                ev,
  618.                 ODFrame*                    frame,
  619.                 ODFrame*                    sourceFrame
  620.             )
  621. {
  622.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  623.     SOMMethodDebug("TextEditor","AttachSourceFrame");
  624.  
  625.     SOM_TRY
  626.     
  627.         // Tell the new frame about its source.
  628.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  629.         frameInfo->SetSourceFrame(ev, sourceFrame);
  630.         
  631.         // And tell the source about its new dependent.
  632.         frameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
  633.         frameInfo->SetDependentFrame(ev, frame);
  634.         
  635.         // In both cases, refcounting of the frame and sourceFrame is
  636.         // handled by the CFrameInfo class.
  637.             
  638.     SOM_CATCH_ALL
  639.     SOM_ENDTRY
  640. }
  641.  
  642. //------------------------------------------------------------------------------
  643. // Method:        ViewTypeChanged
  644. // Origin:        ODPart
  645. //
  646. // Description:    This method is called in response to one of our display frame's
  647. //                viewType field being modified. We call this method on ourselves
  648. //                when new display frames are added, but it call also be called
  649. //                when the user changes the view in the "part info" dialog.
  650. //
  651. //                The part first loads the appropriate view icons if needed and
  652. //                then calculates a new "used" shape based on the bounds of the
  653. //                new view type. If any problems occur while changing the view,
  654. //                the part defaults back to frame view (the part's default view).
  655. //------------------------------------------------------------------------------
  656. #pragma segment TextEditorLayout
  657.  
  658. SOM_Scope    void
  659. SOMLINK        TextEditor__ViewTypeChanged
  660.             (
  661.                 SampleCode_TextEditor*        somSelf,
  662.                 Environment*                ev,
  663.                 ODFrame*                    frame
  664.             )
  665. {
  666.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  667.     SOMMethodDebug("TextEditor","ViewTypeChanged");
  668.  
  669.     SOM_TRY
  670.         Handle iconSuite = kODNULL;
  671.         
  672.         ODTypeToken view = frame->GetViewType(ev);
  673.         
  674.         // Prepare to be displayed in a different view.
  675.         if ( view == gGlobals->fThumbnailView )
  676.             somSelf->GenerateThumbnail(ev, frame);
  677.         
  678.         // Change this frame's used shape to match the new view setting.
  679.         TempODShape newUsedShape = somSelf->CalcNewUsedShape(ev, frame);    
  680.         
  681.         frame->Invalidate(ev, kODNULL, kODNULL);
  682.         frame->ChangeUsedShape(ev, newUsedShape, kODNULL);
  683.         frame->Invalidate(ev, kODNULL, kODNULL);
  684.     SOM_CATCH_ALL
  685.     SOM_ENDTRY
  686. }
  687.  
  688. //------------------------------------------------------------------------------
  689. // Method:        CalcNewUsedShape
  690. // Origin:        TextEditor
  691. //
  692. // Description:    This method is called in response to one of display frame's view
  693. //                being changed. The method calculates the appropriate usedShape
  694. //                for the new view type.
  695. //------------------------------------------------------------------------------
  696. #pragma segment TextEditorLayout
  697.  
  698. SOM_Scope    ODShape*
  699. SOMLINK        TextEditor__CalcNewUsedShape
  700.             (
  701.                 SampleCode_TextEditor*        somSelf,
  702.                 Environment*                ev,
  703.                 ODFrame*                    frame
  704.             )
  705. {
  706.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  707.     SOMMethodDebug("TextEditor","CalcNewUsedShape");
  708.  
  709.     ODShape* usedShape = kODNULL;
  710.     
  711.     SOM_TRY
  712.         ODTypeToken view = frame->GetViewType(ev);
  713.         
  714.         // If the view is "frame", we intentionally return a nil shape;
  715.         // doing so, will reset the used shape to equal the frame shape.
  716.     
  717.         if ( view == gGlobals->fLargeIconView 
  718.              || view == gGlobals->fSmallIconView 
  719.              || view == gGlobals->fThumbnailView )
  720.         {
  721.             TRY
  722.                 RgnHandle usedRgn = ODNewRgn();
  723.     
  724.                 TRY
  725.                     Rect bounds;
  726.                     if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  727.                     {
  728.                         CUsingLibraryResources res;
  729.         
  730.                         // Set the bounds rect for the icon size.
  731.                         SetRect(&bounds, 0, 0,
  732.                                     (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
  733.                                     (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
  734.         
  735.                         // Convert the icon mask into a Region.
  736.                         THROW_IF_ERROR(IconIDToRgn(usedRgn, &bounds, atAbsoluteCenter, kBaseResourceID));
  737.                     }
  738.                     else if ( view == gGlobals->fThumbnailView )
  739.                     {    
  740.                         bounds = (**(PicHandle) gGlobals->fThumbnail).picFrame;
  741.                         RectRgn(usedRgn,&bounds);
  742.                     }
  743.                     
  744.                     // We use a temp shape here so that in case of an exception, the usedShape
  745.                     // will still be NULL and doesn't have to be caught and fixed up.
  746.                     TempODShape usedShape = frame->CreateShape(ev);
  747.                     usedShape->SetQDRegion(ev, usedRgn);
  748.                 CATCH_ALL
  749.                     DisposeRgn(usedRgn);
  750.                     RERAISE;
  751.                 ENDTRY
  752.                 
  753.             CATCH_ALL
  754.                 ODSafeReleaseObject(usedShape);
  755.                 usedShape = kODNULL;
  756.             ENDTRY
  757.         }
  758.             
  759.     SOM_CATCH_ALL
  760.     SOM_ENDTRY
  761.  
  762.     return usedShape;
  763. }
  764.  
  765. //------------------------------------------------------------------------------
  766. // Method:        UpdateFrame
  767. // Origin:        TextEditor
  768. //
  769. // Description:    This method is called in response to one of our
  770. //------------------------------------------------------------------------------
  771. #pragma segment TextEditorLayout
  772.  
  773. SOM_Scope    void
  774. SOMLINK        TextEditor__UpdateFrame
  775.             (
  776.                 SampleCode_TextEditor*        somSelf,
  777.                 Environment*                ev,
  778.                 ODFrame*                    frame,
  779.                 ODTypeToken                    view,
  780.                 ODShape*                    usedShape
  781.             )
  782. {
  783.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  784.     SOMMethodDebug("TextEditor","UpdateFrame");
  785.  
  786.     SOM_TRY
  787.     
  788.         // Update the frame to have the new view and UsedShape.
  789.         frame->Invalidate(ev, kODNULL, kODNULL);
  790.         frame->SetViewType(ev, view);
  791.         frame->ChangeUsedShape(ev, usedShape, kODNULL);
  792.         frame->Invalidate(ev, kODNULL, kODNULL);
  793.  
  794.     SOM_CATCH_ALL
  795.     SOM_ENDTRY
  796. }
  797.  
  798. //------------------------------------------------------------------------------
  799. // Method:        FrameShapeChanged
  800. // Origin:        ODPart
  801. //
  802. // Description:    This method is called in response to a frame's shape being
  803. //                altered, either by the user or the part we are embedded in.
  804. //
  805. //                To keep all attached frames in sync, we need to propogate the
  806. //                new frame shape the frames dependent on the changed frame. This
  807. //                is done by observing the display frames stored in the frame info
  808. //                and calling RequestFrameShape for each.
  809. //------------------------------------------------------------------------------
  810. #pragma segment TextEditorLayout
  811.  
  812. SOM_Scope    void
  813. SOMLINK        TextEditor__FrameShapeChanged
  814.             (
  815.                 SampleCode_TextEditor*        somSelf,
  816.                 Environment*                ev,
  817.                 ODFrame*                    frame
  818.             )
  819. {
  820.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  821.     SOMMethodDebug("TextEditor","FrameShapeChanged");
  822.  
  823.     SOM_TRY
  824.     
  825.         if ( frame->GetPresentation(ev) == gGlobals->fMainPresentation )
  826.         {
  827.             // If the frame is the root frame of a part or document window, it should
  828.             // have no effect on its dependent frames or source frame.
  829.         
  830.             if ( !frame->IsRoot(ev) )
  831.             {
  832.                 TempODShape    frameShape = frame->AcquireFrameShape(ev, kODNULL);
  833.                 CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  834.                 
  835.                 if ( frameInfo->HasSourceFrame() )
  836.                 {
  837.                     ODFrame* displayFrame = frameInfo->GetSourceFrame(ev);
  838.                     
  839.                     TempODShape frameShapeCopy = frameShape->Copy(ev);
  840.                     TempODShape returnShape = displayFrame->RequestFrameShape(ev, frameShapeCopy, kODNULL);
  841.         
  842.                     somSelf->CalcTextBounds(ev, displayFrame);
  843.                     displayFrame->Invalidate(ev, kODNULL, kODNULL);
  844.                 }
  845.             
  846.                 if ( frameInfo->HasDependentFrame() )
  847.                 {
  848.                     ODFrame* displayFrame = frameInfo->GetDependentFrame(ev);
  849.                     {
  850.                         displayFrame = frameInfo->GetDependentFrame(ev);
  851.             
  852.                         TempODShape frameShapeCopy = frameShape->Copy(ev);
  853.                         TempODShape returnShape = displayFrame->RequestFrameShape(ev, frameShapeCopy, kODNULL);
  854.                         
  855.                         somSelf->CalcTextBounds(ev, displayFrame);
  856.                         displayFrame->Invalidate(ev, kODNULL, kODNULL);
  857.                     }
  858.                 }
  859.             }
  860.             
  861.             if ( frame->IsRoot(ev) )
  862.             {
  863.                 somSelf->CalcViewRect(ev, frame);
  864.                 somSelf->RepositionScrollbars(ev, frame);
  865.             }
  866.             else
  867.             {
  868.                 // We disable the drawing because focusing to facets when we are
  869.                 // not active is messy. The invalidate call will force redrawing.
  870.                 CTextensionDisplay* display = _fTextension->GetDisplayHandler();
  871.                 display->DisableDrawing();
  872.         
  873.                 // Reset our text bounds.
  874.                 somSelf->CalcTextBounds(ev, frame);
  875.         
  876.                 display->EnableDrawing();
  877.                 frame->Invalidate(ev, kODNULL, kODNULL);
  878.             }
  879.         }
  880.  
  881.     SOM_CATCH_ALL
  882.     SOM_ENDTRY
  883. }
  884.  
  885. //------------------------------------------------------------------------------
  886. // Method:        Open
  887. // Origin:        ODPart
  888. //
  889. // Description:    This method is called when OpenDoc, a containing part, or the
  890. //                active editor would like to open a frame into a seperate window.
  891. //                If a source frame is passed into this method, the editor is
  892. //                being asked one of two things. If the frame is the root, we are
  893. //                being asked to open an existing document. If the frame is not
  894. //                the root, we are being asked to open a part window. If a source
  895. //                frame is not specified, the editor is being asked to open a new
  896. //                window.
  897. //------------------------------------------------------------------------------
  898. #pragma segment TextEditorLayout
  899.  
  900. SOM_Scope    ODID
  901. SOMLINK        TextEditor__Open
  902.             (
  903.                 SampleCode_TextEditor*        somSelf,
  904.                 Environment*                ev,
  905.                 ODFrame*                    frame
  906.             )
  907. {
  908.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  909.     SOMMethodDebug("TextEditor","Open");
  910.  
  911.     ODID windowID = kODNULLID;
  912.  
  913.     SOM_TRY
  914.     
  915.         WindowProperties* windowProperties = kODNULL;
  916.         ODVolatile(windowProperties);
  917.     
  918.         TRY
  919.             TempODWindow window = kODNULL;
  920.  
  921.             // Because the frame parameter being passed to us can be one of
  922.             // three things, we must determine what it is; either the root
  923.             // frame of a existing document, the source frame for a part
  924.             // window, or null if we are opening a new document.
  925.         
  926.             if ( frame == kODNULL )
  927.             {
  928.                 // Calculate the bounding rectangle for a new window
  929.                 Rect windowRect = somSelf->CalcPartWindowSize(ev, kODNULL);
  930.                 // Get the default setting for a document window.
  931.                 windowProperties = somSelf->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  932.                 // Create a Mac Window and register it with OpenDoc.
  933.                 window = somSelf->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  934.             }
  935.             else if ( frame->IsRoot(ev) )
  936.             {
  937.                 // Get the previously saved settings for the document window.
  938.                 windowProperties = somSelf->GetSavedWindowProperties(ev, frame);
  939.                 
  940.                 if ( windowProperties == kODNULL )
  941.                 {
  942.                     // Calculate the bounding rectangle for a new window
  943.                     Rect windowRect = somSelf->CalcPartWindowSize(ev, frame);
  944.                     // Get the default setting for a document window.
  945.                     windowProperties = somSelf->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  946.                 }
  947.     
  948.                 // Create a Mac Window and register it with OpenDoc.
  949.                 window = somSelf->CreateWindow(ev, frame, kODFrameObject, windowProperties);
  950.  
  951.                 // We bumped the ref count of the sourceFrame in GetSavedWindowProperties
  952.                 // to prevent it from being released too early. We release it here because
  953.                 // we are done accessing it.
  954.                 ODReleaseObject(ev, windowProperties->sourceFrame);
  955.             }
  956.             else // frame is a source frame
  957.             {
  958.     /*
  959.                 window = somSelf->AcquireFramesWindow(ev, frame);
  960.         
  961.                 if ( window == kODNULL )
  962.                 {
  963.                     // Calculate the bounding rectangle for a new window
  964.                     Rect windowRect = this->CalcPartWindowSize(ev, frame);
  965.                     // Get the default setting for a document window.
  966.                     windowProperties = somSelf->GetDefaultWindowProperties(ev, frame, windowRect);
  967.                     // Create a Mac Window and register it with OpenDoc.
  968.                     window = somSelf->CreateWindow(ev, kODNULL, kODNonPersistentFrameObject, windowProperties);
  969.                                     
  970.                     // Tell the source frame that it is opened in a part window.
  971.                     CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  972.                     frameInfo->SetPartWindow(window);
  973.                 }
  974.     */
  975.                 // Multiple window support has not yet been implemented.
  976.                 somSelf->DoDialogBox(ev, frame, kErrorBoxID, kErrUnimplemented);
  977.                 THROW(kODErrAlreadyNotified);
  978.             }
  979.         
  980.             // Creates the root facet for the window and notifies the
  981.             // part.
  982.             window->Open(ev);
  983.             // Makes the window visible.
  984.             window->Show(ev);
  985.             // Activates and selects the window.
  986.             window->Select(ev);
  987.         
  988.             // Cleanup allocated memory.
  989.             ODDeleteObject(windowProperties);
  990.         
  991.             // Get window id to return.
  992.             windowID = (window ? window->GetID(ev) : kODNULLID);
  993.         
  994.         CATCH_ALL
  995.             // If we threw early, the source frame's refcount may be too high.
  996.             if ( windowProperties )
  997.                 ODSafeReleaseObject(windowProperties->sourceFrame);
  998.             // Cleanup the created items.
  999.             ODDeleteObject(windowProperties);
  1000.             windowID = kODNULLID;
  1001.             // Alert the caller.
  1002.             RERAISE;
  1003.         ENDTRY
  1004.     
  1005.     SOM_CATCH_ALL
  1006.         windowID = kODNULLID;
  1007.     SOM_ENDTRY
  1008.  
  1009.     return windowID;
  1010. }
  1011.  
  1012. //------------------------------------------------------------------------------
  1013. // Method:        AcquireFramesWindow
  1014. // Origin:        TextEditor
  1015. //
  1016. // Description:    This method is called by the part when a frame, that has been
  1017. //                previously opened, is being opened again.
  1018. //
  1019. //                The method retrieves the existing window for the frame and
  1020. //                returns it.                
  1021. //------------------------------------------------------------------------------
  1022. #pragma segment TextEditorLayout
  1023.  
  1024. SOM_Scope    ODWindow*  
  1025. SOMLINK        TextEditor__AcquireFramesWindow
  1026.             (
  1027.                 SampleCode_TextEditor*        somSelf, 
  1028.                 Environment*                ev,
  1029.                 ODFrame*                    frame
  1030.             )
  1031. {
  1032.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1033.     SOMMethodDebug("TextEditor","GetFramesWindow");
  1034.  
  1035.     ODWindow* window = kODNULL;
  1036.     
  1037.     SOM_TRY
  1038.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1039.         ODWindow* window = frameInfo->AcquirePartWindow(ev);
  1040.     SOM_CATCH_ALL
  1041.         window = kODNULL;
  1042.     SOM_ENDTRY
  1043.     
  1044.     return window;
  1045. }
  1046.  
  1047. //------------------------------------------------------------------------------
  1048. // Method:        CreateWindow
  1049. // Origin:        TextEditor
  1050. //
  1051. // Description:    This method is called by the part when a window needs to be
  1052. //                created for a frame being opened.
  1053. //
  1054. //                The part uses the information passed in windowProperties to 
  1055. //                create the appropriate window. The generated window is
  1056. //                registered with OpenDoc as a new window (RegisterWindow) or as a
  1057. //                window from an existing document (RegisterWindowForFrame).
  1058. //------------------------------------------------------------------------------
  1059. #pragma segment TextEditorLayout
  1060.  
  1061. SOM_Scope    ODWindow*
  1062. SOMLINK        TextEditor__CreateWindow 
  1063.             (
  1064.                 SampleCode_TextEditor*        somSelf,
  1065.                 Environment*                ev,
  1066.                 ODFrame*                    frame,
  1067.                 ODType                        frameType, 
  1068.                 WindowProperties*            windowProperties
  1069.             )
  1070. {
  1071.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1072.     SOMMethodDebug("TextEditor","CreateWindow");
  1073.  
  1074.     ODWindow* window = kODNULL;
  1075.     ODVolatile(window);
  1076.  
  1077.     SOM_TRY
  1078.     
  1079.         ODPlatformWindow platformWindow = kODNULL;
  1080.         
  1081.         // Using the name and the calculated rectangle, create a new window.
  1082.         platformWindow = NewCWindow((Ptr) ODNewPtr(sizeof(WindowRecord)),
  1083.                                     &windowProperties->boundsRect,
  1084.                                     windowProperties->title,
  1085.                                     kODFalse,                                // visible
  1086.                                     windowProperties->procID,
  1087.                                     (WindowPtr) -1L,
  1088.                                     windowProperties->hasCloseBox,
  1089.                                     windowProperties->refCon);
  1090.     
  1091.         if ( platformWindow )
  1092.         {
  1093.             TRY
  1094.                 ODWindowState* windowState = ODGetSession(ev, somSelf)->GetWindowState(ev);
  1095.                 
  1096.                 ODBoolean saveWindow = ODISOStrEqual(frameType, kODFrameObject);
  1097.                 
  1098.                 // Tell the window object that we will be disposing the window record
  1099.                 // when the root frame is closed/removed.
  1100.                 ODBoolean shouldDispose = kODFalse;
  1101.                 
  1102.                 // Determine whether we are creating a new window (frame is null),
  1103.                 // or opening a previous saved window (frame is valid).
  1104.                 
  1105.                 if ( frame == kODNULL )
  1106.                 {                                
  1107.                     // Tell OpenDoc about it by creating an OpenDoc window object.
  1108.                     window = windowState->
  1109.                                 RegisterWindow(ev, 
  1110.                                     platformWindow,                    // Macintosh WindowPtr
  1111.                                     frameType,                        // Frame type (Persistent/Non-persistent)
  1112.                                     windowProperties->isRootWindow,    // Is this a document window?
  1113.                                     windowProperties->isResizable,    // Is this window resizeable?
  1114.                                     windowProperties->isFloating,    // Is this window floating?
  1115.                                     saveWindow,                        // Should this window be persistent?
  1116.                                     shouldDispose,                    // (see comment above)
  1117.                                     _fSelf,                            // Part reference to us
  1118.                                     gGlobals->fFrameView,            // What view should the window have?
  1119.                                     gGlobals->fMainPresentation,    // What presentation should the window have?
  1120.                                     windowProperties->sourceFrame);    // The display frame being opened, if any
  1121.                 }
  1122.                 else
  1123.                 {
  1124.                     // Tell OpenDoc about it by creating an OpenDoc window object.
  1125.                     window = windowState->
  1126.                                 RegisterWindowForFrame(ev, 
  1127.                                     platformWindow,                    // Macintosh WindowPtr
  1128.                                     frame,                             // Frame type (Persistent/Non-persistent)
  1129.                                     windowProperties->isRootWindow,    // Is this a document window?
  1130.                                     windowProperties->isResizable,    // Is this window resizeable?
  1131.                                     windowProperties->isFloating,    // Is this window floating?
  1132.                                     saveWindow,                        // Should this window be persistent?
  1133.                                     shouldDispose,                    // (see comment above)
  1134.                                     windowProperties->sourceFrame);    // The display frame being opened, if any
  1135.                 }
  1136.                                     
  1137.             CATCH_ALL
  1138.                 // Cleanup Macintosh Window.
  1139.                 CloseWindow(platformWindow);
  1140.                 ODDisposePtr(platformWindow);
  1141.                 // Cleanup OpenDoc Window.
  1142.                 ODSafeReleaseObject(window);
  1143.                 window = kODNULL;
  1144.                 // Get the right error message for the problem.
  1145.                 ODSShort errMsgNum = (!frame && windowProperties->sourceFrame)
  1146.                                         ? kErrCantOpenPartWindow : kErrCantOpenDocWindow;
  1147.                 // Alert the user of the problem.
  1148.                 somSelf->DoDialogBox(ev, frame, kErrorBoxID, errMsgNum);
  1149.                 // Change the exception value, so the DocShell doesn't display an
  1150.                 // error dialog.
  1151.                 SetErrorCode(kODErrAlreadyNotified);
  1152.                 // Alert the caller.
  1153.                 RERAISE;
  1154.             ENDTRY
  1155.         }
  1156.     
  1157.     SOM_CATCH_ALL
  1158.         window = kODNULL;
  1159.     SOM_ENDTRY
  1160.  
  1161.     return window;
  1162. }
  1163.  
  1164. //------------------------------------------------------------------------------
  1165. // Method:        CleanupWindow
  1166. // Origin:        TextEditor
  1167. //
  1168. // Description:    This method is called by the part when a window needs to be
  1169. //                cleaned up for a frame being closed/removed.
  1170. //
  1171. //                The part deallocates the window buffer allocated in the
  1172. //                CreateWindow() method.
  1173. //------------------------------------------------------------------------------
  1174. #pragma segment TextEditorLayout
  1175.  
  1176. SOM_Scope    void
  1177. SOMLINK        TextEditor__CleanupWindow
  1178.             (
  1179.                 SampleCode_TextEditor*        somSelf,
  1180.                 Environment*                ev,
  1181.                 ODFrame*                    frame
  1182.             )
  1183. {
  1184.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1185.     SOMMethodDebug("TextEditor","CleanupWindow");
  1186.  
  1187.     SOM_TRY
  1188.     
  1189.            TRY
  1190.             CFrameInfo*    frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1191.             if ( frameInfo->ShouldDisposeWindow() )
  1192.             {
  1193.                 TempODWindow window = frame->AcquireWindow(ev);
  1194.                 THROW_IF_NULL(window);
  1195.                 
  1196.                 ODPlatformWindow windowPtr = window->GetPlatformWindow(ev);
  1197.                 CloseWindow(windowPtr);
  1198.                 ODDisposePtr(windowPtr);
  1199.             }
  1200.         CATCH_ALL
  1201.             somSelf->DoDialogBox(ev, frame, kErrorBoxID, kErrWindowGone);
  1202.             // consume excpetion because it's not fatal.
  1203.         ENDTRY
  1204.     
  1205.     SOM_CATCH_ALL
  1206.     SOM_ENDTRY
  1207. }
  1208.  
  1209. //------------------------------------------------------------------------------
  1210. // Method:        GetDefaultWindowProperties
  1211. // Origin:        TextEditor
  1212. //
  1213. // Description:    This method is called by the part when a new window is being
  1214. //                created. The method examines the frame which is being opened
  1215. //                a generates the default window parameters to pass to the
  1216. //                Mac Toolbox.
  1217. //------------------------------------------------------------------------------
  1218. #pragma segment TextEditorLayout
  1219.  
  1220. SOM_Scope    WindowProperties*
  1221. SOMLINK        TextEditor__GetDefaultWindowProperties
  1222.             (
  1223.                 SampleCode_TextEditor*        somSelf,
  1224.                 Environment*                ev,
  1225.                 ODFrame*                    sourceFrame,
  1226.                 Rect*                        windowRect
  1227.             )
  1228. {
  1229.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1230.     SOMMethodDebug("TextEditor","GetDefaultWindowProperties");
  1231.  
  1232.     WindowProperties* windowProperties = kODNULL;
  1233.     ODVolatile(windowProperties);
  1234.     
  1235.     SOM_TRY
  1236.         windowProperties = new WindowProperties;
  1237.     
  1238.         // Calculate the offset for the window based on the sourceFrame.    
  1239.         if ( sourceFrame )
  1240.             somSelf->CalcPartWindowPosition(ev, sourceFrame, windowRect);
  1241.         else
  1242.             OffsetRect(windowRect, kALittleNudge,
  1243.                         GetMBarHeight() + kMacWindowTitleBarHeight);
  1244.     
  1245.         windowProperties->boundsRect = *windowRect;
  1246.     
  1247.         // Get the part's name to use for the new window.
  1248.         TempODIText windowName = GetPartName(ev, somSelf, kODCategoryStyledText);
  1249.         // Convert the ODIText into a Pascal string.
  1250.         GetITextString(windowName, windowProperties->title);
  1251.         
  1252.         // Fill in the other fields of the Window Properties struct.
  1253.         windowProperties->procID = zoomDocProc;
  1254.         windowProperties->hasCloseBox = kODTrue;
  1255.         windowProperties->refCon = (long) kODNULL;
  1256.         windowProperties->wasVisible = kODFalse;
  1257.         windowProperties->isResizable = kODTrue;
  1258.         windowProperties->isFloating = kODFalse;
  1259.         windowProperties->isRootWindow = sourceFrame ? kODFalse : kODTrue;
  1260.         windowProperties->shouldShowLinks = kODFalse;
  1261.         windowProperties->sourceFrame = sourceFrame;
  1262.         
  1263.     SOM_CATCH_ALL
  1264.         ODDeleteObject(windowProperties);
  1265.     SOM_ENDTRY
  1266.  
  1267.     return windowProperties;
  1268. }
  1269.  
  1270. //------------------------------------------------------------------------------
  1271. // Method:        GetSavedWindowProperties
  1272. // Origin:        TextEditor
  1273. //
  1274. // Description:    This method is called by the part to read in saved information
  1275. //                for a window from an existing document.
  1276. //------------------------------------------------------------------------------
  1277. #pragma segment TextEditorLayout
  1278.  
  1279. SOM_Scope    WindowProperties*
  1280. SOMLINK        TextEditor__GetSavedWindowProperties
  1281.             (
  1282.                 SampleCode_TextEditor*        somSelf,
  1283.                 Environment*                ev,
  1284.                 ODFrame*                    frame
  1285.             )
  1286. {
  1287.     SOMMethodDebug("TextEditor","GetSavedWindowProperties");
  1288.  
  1289.     WindowProperties* windowProperties = kODNULL;
  1290.     ODVolatile(windowProperties);
  1291.  
  1292.     SOM_TRY
  1293.     
  1294.         windowProperties = new WindowProperties;
  1295.  
  1296.         // If we fail to load the window properties from storage, delete
  1297.         // the structure so the calling code will behave appropriately.    
  1298.         if ( BeginGetWindowProperties(ev, frame, windowProperties) )
  1299.         {
  1300.             // Note: We don't call EndGetWindowProperties because it releases the source
  1301.             // frame, which we will need after this method returns.
  1302.             
  1303.             // Get the part's name to use for the new window.
  1304.             TempODIText windowName = GetPartName(ev, somSelf, kODCategoryStyledText);
  1305.             // Convert the ODIText into a Pascal string.
  1306.             GetITextString(windowName, windowProperties->title);
  1307.             
  1308.             // Verify the window is still visible on a monitor.
  1309.             
  1310.             RgnHandle windowRgn = ODNewRgn();
  1311.             ODBoolean repositionWindow = kODFalse;
  1312.             
  1313.             // We are only concerned with the window's title bar being
  1314.             // visible, so calcuate the titlebar rect from the current
  1315.             // window bounds.
  1316.             Rect adjustedBounds = windowProperties->boundsRect;
  1317.             adjustedBounds.bottom = adjustedBounds.top;
  1318.             adjustedBounds.top -= kMacWindowTitleBarHeight;
  1319.             
  1320.             // Intersect the monitor's region
  1321.             RectRgn(windowRgn, &adjustedBounds);
  1322.             SectRgn(windowRgn, GetGrayRgn(), windowRgn);
  1323.             
  1324.             if ( !EmptyRgn(windowRgn) )
  1325.             {
  1326.                 // If the visible portion of the window is too small, we need
  1327.                 // to reposition it.
  1328.                 Rect intersectedBounds = (**windowRgn).rgnBBox;
  1329.                 if ( (intersectedBounds.right - intersectedBounds.left < kMinHorzVisPortion) ||
  1330.                      (intersectedBounds.bottom - intersectedBounds.top < kMinVertVisPortion) )
  1331.                     repositionWindow = kODTrue;
  1332.             }
  1333.             else
  1334.             {
  1335.                 // If the window is completely offscreen, we need to reposition it.
  1336.                 repositionWindow = kODTrue;
  1337.             }
  1338.             ODDisposeHandle((ODHandle) windowRgn);
  1339.             
  1340.             // If not, we need to move it so the user can see it.
  1341.             if ( repositionWindow )
  1342.             {
  1343.                 Rect windowRect = (windowProperties->boundsRect);
  1344.                 // Move the window to {0,0} coordinates.
  1345.                 OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
  1346.                 // Now move the window to the default window position.
  1347.                 OffsetRect(&windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight);
  1348.                 // Save the new window position in our windowProperties.
  1349.                 windowProperties->boundsRect = windowRect;
  1350.             }
  1351.         }
  1352.         else
  1353.         {
  1354.             // If we were unable to re-load window properties, dispose of the
  1355.             // struct.
  1356.             ODDeleteObject(windowProperties);
  1357.         }
  1358.     SOM_CATCH_ALL
  1359.         ODDeleteObject(windowProperties);
  1360.     SOM_ENDTRY
  1361.  
  1362.     return windowProperties;
  1363. }
  1364.  
  1365. //------------------------------------------------------------------------------
  1366. // Method:        CalcPartWindowSize
  1367. // Origin:        TextEditor
  1368. //
  1369. // Description:    This method is called by the part to determine what size a new
  1370. //                window shoud be.
  1371. //------------------------------------------------------------------------------
  1372. #pragma segment TextEditorLayout
  1373.  
  1374. SOM_Scope    Rect
  1375. SOMLINK        TextEditor__CalcPartWindowSize
  1376.              (
  1377.                 SampleCode_TextEditor*        somSelf,
  1378.                 Environment*                ev,
  1379.                 ODFrame*                    sourceFrame
  1380.             )
  1381. {
  1382.     SOMMethodDebug("TextEditor","CalcPartWindowSize");
  1383.  
  1384.     Rect windowRect = { 0, 0, 0, 0 };
  1385.  
  1386.     SOM_TRY
  1387.     
  1388.         const ODSShort kOnePageWidth = 600;
  1389.         
  1390.         ODRect    frameRect;
  1391.         
  1392.         // If a source frame is given, the part is being asked to open one of
  1393.         // its display frames into a part window. Otherwise, we are being opened
  1394.         // as the root frame of the current document and should size the window
  1395.         // accordingly.
  1396.         
  1397.         if (sourceFrame)
  1398.         {
  1399.             // Set up the window's size to be that of the display frame being opened.
  1400.             
  1401.             // Retrieve the fixed point bounding box for the frame.
  1402.             TempODShape frameShape = sourceFrame->AcquireFrameShape(ev, kODNULL);
  1403.             frameShape->GetBoundingBox(ev, &frameRect);
  1404.             
  1405.             // Convert that into a Quickdraw rectangle.
  1406.             FixedToIntRect(frameRect, windowRect);
  1407.         }
  1408.         else
  1409.         {
  1410.             // (3 * kODLargeIconSize) prevents the window from covering the volume
  1411.             // icons on the desktop which is a violation of Macintosh HI Guidelines.
  1412.             
  1413.             SetRect(&windowRect, 0, 0,
  1414.                       ODQDGlobals.screenBits.bounds.right - (3 * kODLargeIconSize),
  1415.                       ODQDGlobals.screenBits.bounds.bottom
  1416.                           - GetMBarHeight() - kMacWindowTitleBarHeight - kALittleNudge);        
  1417.             
  1418.             if ( windowRect.right - windowRect.left > kOnePageWidth )
  1419.                 windowRect.right = windowRect.left + kOnePageWidth;
  1420.         }
  1421.         
  1422.     SOM_CATCH_ALL
  1423.     SOM_ENDTRY
  1424.  
  1425.     return windowRect;
  1426. }
  1427.  
  1428. //------------------------------------------------------------------------------
  1429. // Method:        CalcPartWindowPosition
  1430. // Origin:        TextEditor
  1431. //
  1432. // Description:    This method is called by the part to determine where to align
  1433. //                the new window (top left corner of the screen or tiled to a
  1434. //                frame).
  1435. //------------------------------------------------------------------------------
  1436. #pragma segment TextEditorLayout
  1437.  
  1438. SOM_Scope    Rect
  1439. SOMLINK        TextEditor__CalcPartWindowPosition
  1440.              (
  1441.                 SampleCode_TextEditor*        somSelf,
  1442.                 Environment*                ev,
  1443.                 ODFrame*                    frame,
  1444.                 Rect*                        partWindowBounds
  1445.             )
  1446. {
  1447.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1448.     SOMMethodDebug("TextEditor","CalcPartWindowPosition");
  1449.  
  1450.     SOM_TRY
  1451.     
  1452.         ODFacet*        activeFacet;
  1453.         ODRect            bbox;
  1454.         Rect            bounds;
  1455.         
  1456.         // We need to know which facet of the frame we are opening to position
  1457.         // the child window.
  1458.         activeFacet = somSelf->GetActiveFacetForFrame(ev, frame);
  1459.         
  1460.         // This should never occur, but if it did, it would be fatal.
  1461.         // So we will just pass back the same rectangle.
  1462.         if ( activeFacet == kODNULL )
  1463.             return *partWindowBounds;
  1464.         
  1465.         // For the purposes of tiling, we need the to know the area of the
  1466.         // document the frame occupies. We do this by getting the bouding
  1467.         // box and offsetting it by the aggregate external window transform
  1468.         // of the facet.
  1469.         
  1470.         TempODShape frameShape = activeFacet->GetFrame(ev)->AcquireFrameShape(ev, kODNULL);
  1471.         TempODShape boundsShape = frameShape->Copy(ev);
  1472.     
  1473.         TempODTransform windowFrameTransform = activeFacet->AcquireWindowFrameTransform(ev, kODNULL);
  1474.     
  1475.         // Translate the bounds rect into window coordinates.
  1476.         boundsShape->Transform(ev, windowFrameTransform);
  1477.         
  1478.         // Get and convert the bounding box into a QuickDraw rectangle.
  1479.         boundsShape->GetBoundingBox(ev, &bbox);
  1480.         FixedToIntRect(bbox, bounds);
  1481.             
  1482.         // We then call our method to tile the child window.
  1483.         *partWindowBounds = TilePartWindow(ev, &bounds, partWindowBounds);
  1484.         
  1485.         // Set the port and origin so we can convert the rect to
  1486.         // global Window Mgr coordinates.
  1487.         SetPort(activeFacet->GetCanvas(ev)->GetQDPort(ev));
  1488.         SetOrigin(0,-kMacWindowTitleBarHeight);
  1489.         
  1490.         // Convert the local coordinates to global Window Mgr coordinates.
  1491.         LocalToGlobal((Point*) &partWindowBounds->top);
  1492.         LocalToGlobal((Point*) &partWindowBounds->bottom);
  1493.  
  1494.     SOM_CATCH_ALL
  1495.     SOM_ENDTRY
  1496.  
  1497.     return *partWindowBounds;
  1498. }
  1499.  
  1500. //------------------------------------------------------------------------------
  1501. // Method:        GetActiveFacetForFrame
  1502. // Origin:        TextEditor
  1503. //
  1504. // Description:    This method is called by the part when it needs to know what the
  1505. //                active facet is for the part, if any.
  1506. //
  1507. //                The part uses this method specifically to find the facet of a
  1508. //                source frame when opening a part window.
  1509. //------------------------------------------------------------------------------
  1510. #pragma segment TextEditorLayout
  1511.  
  1512. SOM_Scope    ODFacet*
  1513. SOMLINK        TextEditor__GetActiveFacetForFrame
  1514.              (
  1515.                 SampleCode_TextEditor*        somSelf,
  1516.                 Environment*                ev,
  1517.                 ODFrame*                    frame
  1518.             )
  1519. {
  1520.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1521.     SOMMethodDebug("TextEditor","GetActiveFacetForFrame");
  1522.  
  1523.     ODFacet* facet = kODNULL;
  1524.     
  1525.     SOM_TRY
  1526.     
  1527.         CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  1528.         
  1529.         // If the frame is active, and it should be, get the active facet
  1530.         // from the frame state info.
  1531.         if ( frameInfo->IsFrameActive() )
  1532.         {
  1533.             facet = frameInfo->GetActiveFacet();
  1534.         }
  1535.         else
  1536.         // Otherwise, iterate over the display frames looking for one
  1537.         // that has an active facet... there should be at least one.
  1538.         {
  1539.             TempODFrameFacetIterator fiter(ev, frame);
  1540.             for (ODFacet* selectedFacet = fiter.First(); fiter.IsNotComplete();
  1541.                  selectedFacet = fiter.Next() )
  1542.             {
  1543.                 if ( selectedFacet->IsSelected(ev) )
  1544.                 {
  1545.                     facet = selectedFacet;
  1546.                     break;
  1547.                 }
  1548.             }
  1549.         }
  1550.         
  1551.         // If there are no active facets anywhere, this method should never
  1552.         // have been called, so signal an error.
  1553.         if (facet == kODNULL)
  1554.             THROW(kODErrInvalidFrame);
  1555.             
  1556.     SOM_CATCH_ALL
  1557.         facet = kODNULL;
  1558.     SOM_ENDTRY
  1559.  
  1560.     return facet;
  1561. }
  1562.  
  1563. //------------------------------------------------------------------------------
  1564. // Method:        SequenceChanged
  1565. // Origin:        ODPart
  1566. //
  1567. // Description:    This method is called by
  1568. //------------------------------------------------------------------------------
  1569. #pragma segment TextEditorLayout
  1570.  
  1571. SOM_Scope    void
  1572. SOMLINK        TextEditor__SequenceChanged
  1573.             (
  1574.                 SampleCode_TextEditor*        somSelf, 
  1575.                 Environment*                ev,
  1576.                 ODFrame*                    frame
  1577.             )
  1578. {
  1579.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1580.     SOMMethodDebug("TextEditor","SequenceChanged");
  1581. }
  1582.  
  1583. //------------------------------------------------------------------------------
  1584. // Method:        ContainingPartPropertiesUpdated
  1585. // Origin:        ODPart
  1586. //
  1587. // Description:    This method is called by
  1588. //------------------------------------------------------------------------------
  1589. #pragma segment TextEditorLayout
  1590.  
  1591. SOM_Scope    void
  1592. SOMLINK        TextEditor__ContainingPartPropertiesUpdated
  1593.             (
  1594.                 SampleCode_TextEditor*        somSelf, 
  1595.                 Environment*                ev,
  1596.                 ODFrame*                    frame,
  1597.                 ODStorageUnit*                propertyUnit
  1598.             )
  1599. {
  1600.     SampleCode_TextEditorData *somThis = SampleCode_TextEditorGetData(somSelf);
  1601.     SOMMethodDebug("TextEditor","ContainingPartPropertiesUpdated");
  1602. }
  1603.  
  1604.  
  1605.  
  1606.